
// PaneView.cpp : implementation of the CPaneView class
//

#include "stdafx.h"

#include "csvline.h"
#include "infdoc.h"
#include "PaneView.h"

#include <utility>
#include "propage.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

typedef std::pair<LPCWSTR, LPCWSTR>	TNAMEDESC;
enum { CODE_PAGE = 0, COUNT_LINES, THE_BOM };
static const TNAMEDESC	name2desc[4] = { 
	TNAMEDESC(L"encoding", L"character set"),
	TNAMEDESC(L"count",	L"count of extracted lines"),
	TNAMEDESC(L"BOM",	L"Byte-Order Mark"),
	TNAMEDESC(L"", L"")
};

UINT CPaneView::getWidth(CFrameWnd * pWnd, int thewidth)
{
	//NT thewidth = theApp.GetProfileIntW(L"window", L"pane", (2 * m_colwidth));
	if (thewidth < m_colwidth) thewidth = 2 * m_colwidth;

	RECT therect = {0, 0, 0, 0};
		pWnd->GetClientRect(& therect);
	if(therect.right > therect.left)
	{
		int thechip = ::GetSystemMetrics(SM_CXICON) + ::GetSystemMetrics(SM_CYICON);
		int thesize = (therect.right - therect.left);
		if (thesize > (2 * thechip))
			if (thewidth > (thesize - thechip)) 
				thewidth = (thesize >> 1);
	}

	if (thewidth > ::GetSystemMetrics(SM_CXSCREEN)) thewidth = 2 * m_colwidth;

	return thewidth;
}

// CPaneView

IMPLEMENT_DYNCREATE(CPaneView, CView)

BEGIN_MESSAGE_MAP(CPaneView, CView)
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
	ON_WM_CREATE()
	ON_MESSAGE(WM_DDE_TERMINATE, CPaneView::OnNextLineDDE)
	ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, CPaneView::OnIdleUpdateCmdUI)
	ON_COMMAND(ID_EDIT_COPY, CPaneView::OnEditCopy)
	ON_COMMAND(ID_EDIT_CUT, CPaneView::OnEditRemove)
	ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, CPaneView::OnUpdateEditSel)
	ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, CPaneView::OnUpdateEditSel)
	ON_WM_CONTEXTMENU()
	ON_WM_SETFOCUS()
END_MESSAGE_MAP()

// CPaneView construction/destruction

BOOL CPaneView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying the CREATESTRUCT cs
	cs.dwExStyle = WS_EX_TRANSPARENT; // WS_EX_CONTROLPARENT
	return CView::PreCreateWindow(cs);
}

CPaneView::CPaneView() { m_pPropList = new CDVKProGridCtrl; }

CPaneView::~CPaneView() { delete m_pPropList; }

void CPaneView::OnInitialUpdate()
{
	BOOL bFileSec = TRUE;
	if (m_pPropList->GetPropertyCount()) 
		bFileSec = (m_pPropList->GetProperty(0))->IsVisible();
//	CView::OnUpdate(NULL, 0, NULL);        // initial update

	// TODO: You may populate your TreeView with items by directly 
	//	accessing its tree control through a call to GetTreeCtrl().

//	this->GetClientRect(& rectPropList);
	m_pPropList->RemoveAll();
	CinfDoc* pDoc = GetDocument();
	if (pDoc)	//	loading file section
	{
		const LPFILESEC pData = cmn::getFileSect();
	//OleVariant	thebom(unsigned short(pData->m_cBOM));
		CProPro * pGroup1 = new CProPro(L"file:", (DWORD_PTR) pData, TRUE);
			pGroup1->AllowEdit(FALSE);

		LPCWSTR thename = pDoc->GetPathName();
		if (*thename) pGroup1->SetDescription(thename);
			else pGroup1->SetDescription(pData->getDesc());
//	enum { CODE_PAGE = 0, COUNT_LINES, THE_BOM };
		CProPro * pCodepage = new CProPro( name2desc[CODE_PAGE].first,	// name
										pData->getCodePage(),		// value
										name2desc[CODE_PAGE].second);
			pGroup1->AddSubItem(pCodepage);

		if (pData->m_nSize)
		{
			VARIANT thevar = { VT_UI4 };
				thevar.ulVal = pData->m_nSize;
			pGroup1->AddSubItem(new CDVKPropertyGridProperty(L"size", thevar));
		}

		int nCount = pDoc->getCount();
		if (nCount)
		{
			VARIANT thevar = { VT_INT };
				thevar.intVal = nCount;
			CProPro * pLine = new CProPro( name2desc[COUNT_LINES].first, 
											thevar, //	value
											name2desc[COUNT_LINES].second);
				pLine->AllowEdit(FALSE);
			pGroup1->AddSubItem(pLine);
		}

		if (pData->m_cBOM)
		{
			WCHAR	thebuf[11];
				* thebuf = 0;
			::swprintf(thebuf, 10, L"0x%X", pData->m_cBOM);
			CProPro * pLine = new CProPro( name2desc[THE_BOM].first, thebuf, name2desc[THE_BOM].second);
				pLine->AllowEdit(FALSE);
			if (* thebuf) pGroup1->AddSubItem(pLine);
		}

		m_pPropList->AddProperty(pGroup1);
		pGroup1->Expand(FALSE);
		pGroup1->Show(bFileSec);
	}

	if (GetDocument()->GetPathName().IsEmpty()) return;

	COleVariant	thenull(L"");
	CString thestr;	//	load blank
		thestr.LoadString(IDS_PAIR_NOT_FOUND);
	m_pPropList->AddProperty(new CDVKPropertyGridProperty(NULL, thenull, thestr));

	return;
}

//	CMFCPropertyGridProperty * CPaneView::testBlank(CMFCPropertyGridCtrl * anobj)
//	return anobj->FindItemByData(NULL, FALSE);

BOOL CPaneView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: Add your message handler code here and/or call default
	return TRUE;
	return CView::OnEraseBkgnd(pDC);
}

// CPaneView diagnostics

#ifdef _DEBUG
void CPaneView::AssertValid() const
{
	CView::AssertValid();
}

void CPaneView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CinfDoc* CPaneView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CinfDoc)));
	return (CinfDoc*)m_pDocument;
}
#endif //_DEBUG


// CPaneView message handlers

void CPaneView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);
	// TODO: Add your message handler code here
//	if (nType != SIZE_MINIMIZED) 
	::MoveWindow(m_pPropList->operator HWND(), 0, 0, cx, cy, FALSE);
//	if (cx > 0) theApp.WriteProfileInt(L"window", L"pane", cx);
}

int CPaneView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) < 0) return -1;

	// TODO:  Add your specialized creation code here
	m_pPropList->Create( WS_CHILD | WS_VISIBLE | WS_TABSTOP, 
							CRect(0, 100, 0, 100), 
							this, (UINT)-1);
	//	m_wndPropList.MarkModifiedProperties(TRUE, FALSE);
	SetWindowText(L"PANE");
	return 0;
}

void CPaneView::appendLine(DWORD_PTR aparam)
{
	if(m_pPropList->FindItemByData(aparam, FALSE))
		return; //	already exists

	LPCSVLINE pRec = (LPCSVLINE) aparam;
	std::pair<CString, CString> thepair;
	if (!(pRec->getPair(thepair.first, thepair.second)))
		return;	//	not attr

	CString thestr = L"[]", thesec = pRec->getSec();
	if (thesec.GetLength()) thestr.Format(L"[%s]", thesec);
		m_pPropList->AddProperty(
//			new CMFCPropertyGridProperty(
			new CDVKPropertyGridProperty(
				thepair.first, 
				thepair.second, 
				thestr, 
				aparam) );
	return;
}

LRESULT CPaneView::OnNextLineDDE(WPARAM wParam, LPARAM lParam)
{
	if (wParam) return 0;
	DWORD_PTR pRec = (DWORD_PTR) GetDocument()->getLine(lParam);
		if (pRec) appendLine(pRec);
	return 0;
}

void CPaneView::OnIdleUpdateCmdUI()
{
	CMFCPropertyGridProperty * pBlank = NULL;
	int thelen = m_pPropList->GetPropertyCount();
	if (thelen >> 1) pBlank = m_pPropList->FindItemByData(NULL, FALSE);
	if (pBlank) //	if there are some regular items
	for (int i(1); i < thelen; ++i)
	if (m_pPropList->GetProperty(i)->IsAllowEdit())
	{
		m_pPropList->DeleteProperty(pBlank, FALSE);
		break;
	}
}

void CPaneView::OnEditRemove()
{
	CProPro * pPro = innerCopy();
	if (pPro) 
		if (pPro->GetSubItemsCount()) 
			AfxGetMainWnd()->PostMessageW(WM_COMMAND, ID_VIEW_PANE_HEAD);			
		else {
			pPro = CDVKProGridCtrl::DeleteProperty(m_pPropList, pPro);
			if (!pPro) SetFocus();
		}
	else
		AfxMessageBox(IDS_NO_SEL_ITEMS, MB_OK | MB_ICONWARNING);
}

CMFCPropertyGridProperty * CPaneView::innerCopy()
{
	CMFCPropertyGridProperty * pPro = m_pPropList->GetCurSel();
	if (!pPro) return NULL;
	CString theresult = pPro->GetName();
	if (theresult.Find(L'=') + 1)
		if ((theresult[0]) ^ L'"')
		{
			theresult.Insert(0, L'"');
			theresult.AppendChar(L'"');
		}

	theresult.AppendChar(L'=');
	theresult.Append(pPro->FormatProperty());
	if (theresult.GetLength() >> 1) cmn::ClipboardCopyText(theresult);
		else cmn::ClipboardCopyText(pPro->GetDescription());

	return pPro;
}

void CPaneView::OnEditCopy()
{
	CMFCPropertyGridProperty * pPro = innerCopy();
	if (!pPro) AfxMessageBox(IDS_NO_SEL_ITEMS, MB_OK | MB_ICONWARNING);
}

void CPaneView::OnUpdateEditSel(CCmdUI *pCmdUI)
{
	CMFCPropertyGridProperty * pPro = m_pPropList->GetCurSel();
		pCmdUI->Enable((pPro) ? TRUE : FALSE);
}

void CPaneView::OnContextMenu(CWnd* pWnd, CPoint apoint)
{
	CMFCPropertyGridProperty * pPro = NULL;
	if ((apoint.x + 1) && (apoint.y + 1))
	{
		POINT thepoint = apoint;
		ScreenToClient(& thepoint);
		pPro = m_pPropList->HitTest(thepoint, NULL, TRUE);
	}
	else 
		if (pPro = m_pPropList->GetCurSel())
		{
			m_pPropList->EnsureVisible(pPro);
			CRect rect = pPro->GetRect();
				apoint = rect.CenterPoint();
			ClientToScreen(& apoint);
		}

	if (pPro) {
		cmn::CommonTrackMenu(this, apoint, IDR_MAINFRAME);
//		CommonTrackMenu(this, apoint, CInstApp::EDIT_MENU);
		return;
	}

	AfxGetMainWnd()->PostMessage(WM_CONTEXTMENU, 0, MAKELONG(apoint.x, apoint.y));

}

void CPaneView::OnSetFocus(CWnd* pOldWnd)
{
	CWnd::OnSetFocus(pOldWnd);
	// TODO: Add your message handler code here
	CMFCPropertyGridProperty * pPro = m_pPropList->GetProperty(0);

	if (pOldWnd)
	if (m_pPropList->operator HWND() == pOldWnd->operator HWND())
		return;

	if (!(pPro->IsVisible()))
	if (!(m_pPropList->GetCurSel()))
		if (m_pPropList->GetPropertyCount() > 1)
				m_pPropList->SetCurSel(m_pPropList->GetProperty(1));
			else return;

	m_pPropList->SetFocus();
	return;
}
